/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.stuffrepos.bricknetcenter.http.util;

import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import net.stuffrepos.bricknetcenter.http.HttpParser;
import net.stuffrepos.bricknetcenter.http.HttpResponse;
import org.jaxen.JaxenException;
import org.jaxen.jdom.JDOMXPath;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;

/**
 *
 * @author Eduardo H. Bogoni <eduardobogoni@gmail.com>
 */
public abstract class HtmlParser implements HttpParser {

    private static final String DEFAULT_CONTENT_ENCONDING = "ISO-8859-1";

    public static Object uniqueNode(String xpathPath, Object node) throws JaxenException {
        List results = list(xpathPath, node);

        if (results.isEmpty()) {
            throw new RuntimeException(
                    String.format(
                    "Results is empty (Results: %d, Node: %s, XPath: %s)",
                    results.size(),
                    node,
                    xpathPath));
        }

        return results.get(0);
    }

    public static List list(String xpathPath, Object node) throws JaxenException {
        JDOMXPath xpath = new JDOMXPath(xpathPath);
        xpath.addNamespace("h", "http://www.w3.org/1999/xhtml");
        return xpath.selectNodes(node);
    }

    @Override
    public final void parse(HttpResponse response) throws Exception {
        SAXBuilder builder = new SAXBuilder(org.ccil.cowan.tagsoup.Parser.class.getName());
        Document document = builder.build(parseInputStream(response));
        parseDocument(response, document);
    }

    private static Reader parseInputStream(HttpResponse response) throws UnsupportedEncodingException {
        return new InputStreamReader(response.getInputStream(), getResponseContentEnconding(response));
    }

    private static String getResponseContentEnconding(HttpResponse response) {
        String contentEncoding = response.getContentEncoding();
        if (contentEncoding != null) {
            return contentEncoding;
        } else {
            return DEFAULT_CONTENT_ENCONDING;
        }
    }

    public abstract void parseDocument(HttpResponse response, Document document) throws Exception;

    public static <T> void searchByXpath(String xpathPath, Object node, NodeHandler<T> handler) throws Exception {

        for (Object o : list(xpathPath, node)) {
            handler.handleNode((T) o);
        }
    }

    public static interface NodeHandler<Type> {

        public void handleNode(Type node) throws Exception;
    }
}
